package com.qd.extcam;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;


import android.content.Context;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class ServerAsyncTask extends AsyncTask<Void, Void, String> {

    private Context context;
    private MainActivity activity;
    private boolean running;
    private byte[] queue;
    private int qIndex;
    public static int PRT_POS_DATA = 4;
    public static int PRT_POS_COMMAND = 3;
    public static int PRT_POS_LEN = 1;
    
    
    private InputStream is;
    private OutputStream os;
    
    enum Command {
        PLAY,	
        STOP,
        GET_FILE_LIST,
        GET_FILE
    }
    /**
     * @param context
     * @param statusText
     */
    public ServerAsyncTask(Context context, MainActivity activity) {
        this.context = context;
        this.activity = activity;
        this.queue = new byte[10240];
        this.qIndex = 0;
    }

    private void addQueue(byte[] buff, int nRcvdLen) {
    	System.arraycopy(buff, 0, queue, qIndex, nRcvdLen);
    	qIndex += nRcvdLen;
    }

    
    private void removeQueue(int nPackLen) {
    	System.arraycopy(queue, nPackLen, queue, 0, qIndex - nPackLen);
    	qIndex -= nPackLen;
    }
    
    private void sendPacket(Packet packet){
    	try {
			this.os.write(packet.toBytes());
			this.os.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    private Packet makePacket(Command command, byte[] data)
    {
        Packet packet = new Packet();
        packet.command = (byte)command.ordinal();
        packet.len = (short)(data.length + 6);
        packet.data = data;
        return packet;
    }
    
    private void doPlay(){
    	if(this.activity != null)
    		this.activity.startRecording();
    }
    
    private void doStop() {
    	this.activity.stopRecording();
    }
    
    private void doFileList() {
    	String path = Environment.getExternalStorageDirectory().getAbsolutePath();
    	File file = new File(path);
    	File[] files = file.listFiles();
    	if (files == null) 
    		return;
    	         
    	ArrayList<String> fileList = new ArrayList<String>();
    	for (int i=0; i<files.length; i++) {
    		if ( !files[i].isDirectory()) {
    			fileList.add(files[i].getName());
    		} 
    	}
    	Collections.sort(fileList);
    	String strJson = "";
    	try {
    		JSONArray jArry = new JSONArray();
	    	for(int i=0; i<fileList.size(); i++){
	    		JSONObject json = new JSONObject();
	    		json.put("file", fileList.get(i));
	    		jArry.put(json);
	    	}
	    	strJson = jArry.toString();
    	} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    private void doResponse() {
        byte[] dataBuf = null;
        short nDataLen = 0;
        for(;;){
            // queue에 쌓이 데이타가 PRT_POS_DATA byte보다 작으면
            // 데이타를 더 받아온다.
            if (qIndex <= PRT_POS_DATA)
                break;

            short nPackLen = queue[PRT_POS_LEN];
            if (nPackLen > qIndex)
                break;

            Command cmd = Command.values()[PRT_POS_COMMAND];
            if(queue[PRT_POS_DATA] != 0xf2){
                nDataLen = (short)(nPackLen - 5);
                dataBuf = new byte[nDataLen];
                System.arraycopy(queue, PRT_POS_DATA, dataBuf, 0, nDataLen);
            }

            
           // 완성된 Packet을 MsgQueue에서 제거한다.
            removeQueue(nPackLen);
            
            switch(cmd)
            {
                case PLAY:// Login 시도
                    doPlay();
                    break;
                case STOP:
                    doStop();
                    break;
                case GET_FILE_LIST:
                	break;
                	
            }
        }
    }
    
    @Override
    protected String doInBackground(Void... params) {
        try {
            ServerSocket serverSocket = new ServerSocket(8988);
            Log.d(MainActivity.TAG, "Server: Socket opened");
            Socket client = serverSocket.accept();
            Log.d(MainActivity.TAG, "Server: connection done");
            
            /* Sever - Client 1:1 */ 
            is = client.getInputStream();
            os = client.getOutputStream();
            byte[] buffer = new byte[256];
            int receivedLen = 0;
            while(running){
            	receivedLen = is.read(buffer);
            	if(receivedLen>0){
            		 System.arraycopy(buffer,0,this.queue, this.qIndex, receivedLen);
            		 doResponse();
            	}
            }
            serverSocket.close();
            return null;
        } catch (IOException e) {
            Log.e(MainActivity.TAG, e.getMessage());
            return null;
        }
    }

    /*
     * (non-Javadoc)
     * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
     */
    @Override
    protected void onPostExecute(String result) {
    }

    /*
     * (non-Javadoc)
     * @see android.os.AsyncTask#onPreExecute()
     */
    @Override
    protected void onPreExecute() {
    }
}


class Packet {
    public byte header = (byte)0xf1;
    public byte rslt;
    public byte command;
    public short len;
    public byte[] data;
    public byte tail = (byte)0xf2;
    
    public byte[] toBytes() {
    	int buffer_len = 6 + len;
    	byte[] buffer = new byte[6+len];
    	buffer[0] = header;
    	buffer[1] = rslt;
    	buffer[2] = command;
        System.arraycopy(len, 0, buffer, 3, 2);
        System.arraycopy(data, 0, buffer, 5, len);
        buffer[buffer_len-1] = tail;
        return buffer;
    }
}



